#include "meter.h"
#include "../utils/logger.h"

Meter::Meter(QObject *parent)
    : QObject(parent), m_meterId(0), m_busId(0), m_online(false), m_ua(0.0), m_ub(0.0), m_uc(0.0), m_ia(0.0), m_ib(0.0), m_ic(0.0), m_failureCount(0)
{
}

Meter::Meter(int meterId, const QString &name, int busId, QObject *parent)
    : QObject(parent), m_meterId(meterId), m_name(name), m_busId(busId), m_online(false), m_ua(0.0), m_ub(0.0), m_uc(0.0), m_ia(0.0), m_ib(0.0), m_ic(0.0), m_failureCount(0)
{
}

Meter::Meter(int meterId, const QString &name, const QString &location, int busId, QObject *parent)
    : QObject(parent), m_meterId(meterId), m_name(name), m_location(location), m_busId(busId), m_online(false), m_ua(0.0), m_ub(0.0), m_uc(0.0), m_ia(0.0), m_ib(0.0), m_ic(0.0), m_failureCount(0)
{
}

Meter::~Meter()
{
}

// 设置在线状态
void Meter::setOnline(bool online)
{
    if (m_online != online)
    {
        m_online = online;
        emit onlineChanged();

        Logger::instance()->log(online ? LogLevel::Info : LogLevel::Warning,
                                QString("Meter: 电表 %1 (%2) %3").arg(m_meterId).arg(m_name).arg(online ? "上线" : "离线"));
    }
}

// 设置Ua（不发送信号，统一由updateFromRegisters发送dataUpdated）
void Meter::setUa(double value)
{
    m_ua = value;
}

// 设置Ub（不发送信号，统一由updateFromRegisters发送dataUpdated）
void Meter::setUb(double value)
{
    m_ub = value;
}

// 设置Uc（不发送信号，统一由updateFromRegisters发送dataUpdated）
void Meter::setUc(double value)
{
    m_uc = value;
}

// 设置Ia（不发送信号，统一由updateFromRegisters发送dataUpdated）
void Meter::setIa(double value)
{
    m_ia = value;
}

// 设置Ib（不发送信号，统一由updateFromRegisters发送dataUpdated）
void Meter::setIb(double value)
{
    m_ib = value;
}

// 设置Ic（不发送信号，统一由updateFromRegisters发送dataUpdated）
void Meter::setIc(double value)
{
    m_ic = value;
}

// 从寄存器更新数据
void Meter::updateFromRegisters(const QVector<quint16> &registers)
{
    if (registers.size() < 6)
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("Meter: 电表 %1: 寄存器数据不足，期望6个，实际%2个")
                                    .arg(m_meterId)
                                    .arg(registers.size()));
        return;
    }

    // 更新在线状态
    setOnline(true);

    // 重置失败计数
    resetFailureCount();

    // 解析寄存器数据
    // PM2220寄存器格式：
    // 0x0000: Ua (单位: 0.1V) - 例如 2200 表示 220.0V
    // 0x0002: Ub (单位: 0.1V)
    // 0x0004: Uc (单位: 0.1V)
    // 0x0006: Ia (单位: 0.001A) - 例如 15000 表示 15.0A
    // 0x0008: Ib (单位: 0.001A)
    // 0x000A: Ic (单位: 0.001A)

    setUa(registers[0] * 0.1); // 电压：0.1V单位
    setUb(registers[1] * 0.1);
    setUc(registers[2] * 0.1);
    setIa(registers[3] * 0.001); // 电流：0.001A单位
    setIb(registers[4] * 0.001);
    setIc(registers[5] * 0.001);

    // 更新时间戳
    m_lastUpdateTime = QDateTime::currentDateTime();
    emit lastUpdateTimeChanged();

    // 发送数据更新信号
    emit dataUpdated();

    Logger::instance()->log(LogLevel::Debug,
                            QString("Meter: 电表 %1: Ua=%2V, Ub=%3V, Uc=%4V, Ia=%5A, Ib=%6A, Ic=%7A")
                                .arg(m_meterId)
                                .arg(m_ua, 0, 'f', 1)
                                .arg(m_ub, 0, 'f', 1)
                                .arg(m_uc, 0, 'f', 1)
                                .arg(m_ia, 0, 'f', 3)
                                .arg(m_ib, 0, 'f', 3)
                                .arg(m_ic, 0, 'f', 3));
}

// 计算平均电压
double Meter::averageVoltage() const
{
    return (m_ua + m_ub + m_uc) / 3.0;
}

// 计算平均电流
double Meter::averageCurrent() const
{
    return (m_ia + m_ib + m_ic) / 3.0;
}

// 计算总功率
double Meter::totalPower() const
{
    // 简化计算：P = U * I * 3（三相功率，假设功率因数为1）
    return (m_ua * m_ia + m_ub * m_ib + m_uc * m_ic);
}

// 重置失败计数
void Meter::resetFailureCount()
{
    if (m_failureCount != 0)
    {
        m_failureCount = 0;
        emit failureCountChanged();
    }
}

// 检查是否超时离线
bool Meter::isTimeout(int timeoutSeconds) const
{
    if (!m_lastUpdateTime.isValid())
    {
        return true;
    }

    QDateTime now = QDateTime::currentDateTime();
    qint64 elapsed = m_lastUpdateTime.secsTo(now);

    return elapsed > timeoutSeconds;
}
